home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre1.z / postgre1 / sample / pgstats.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-05-02  |  7.9 KB  |  355 lines

  1. /*    
  2.  *     pgstats -- collect and display statistics on postgres databases
  3.  */
  4. #include <stdio.h>
  5. #include <sys/types.h>
  6. #include <sys/file.h>
  7.  
  8. #ifndef sprite
  9. #include <sys/signal.h>
  10. #endif /* !sprite */
  11.  
  12. #include "tmp/c.h"
  13. #include "tmp/oid.h"
  14. #include "tmp/libpq-fe.h"
  15.  
  16. /* just in case someone left memory debugging turned on... */
  17. #undef palloc
  18. #undef pfree
  19.  
  20. RcsId("$Header: /private/postgres/sample/RCS/pgstats.c,v 1.2 1991/04/12 15:01:22 mao Exp $");
  21.  
  22. typedef struct _dblist_d {
  23.     char        *dbname;
  24.     char        *dbowner;
  25.     ObjectId        dbownerId;
  26.     struct _dblist_d    *next;
  27. } DBLIST_DATA;
  28.  
  29. typedef DBLIST_DATA    *DBLIST;
  30.  
  31. extern char     *getenv();
  32. extern char    *get_attr();
  33. extern DBLIST    build_dblist();
  34. int        count_users();
  35. int        count_dbs();
  36.  
  37. extern char     *PQhost;     /* machine on which the backend is running */
  38. extern char     *PQport;     /* comm. port with the postgres backend. */
  39.  
  40. extern char *optarg;
  41. extern int optind,opterr;
  42.  
  43. char Buf[512];
  44.  
  45. main(argc,argv)
  46.      int argc;
  47.      char **argv;
  48. {
  49.     DBLIST dbs;
  50.     DBLIST old_dbs;
  51.     int nusers, ndbs;
  52.     int  errflag = 0;
  53.     char c;
  54.  
  55.     /* ----------------
  56.      *    process command line options
  57.      * ----------------
  58.      */
  59.     while ((c = getopt(argc, argv, "p:h:")) != EOF) {
  60.     switch(c) {
  61.         case 'h':
  62.             PQhost = optarg;
  63.             break;        
  64.         case 'p':
  65.             PQport = optarg;
  66.             break;
  67.         case '?' :
  68.             errflag++;
  69.         }
  70.     }
  71.  
  72.     if (errflag) {
  73.         fprintf(stderr, "usage: %s [-p port] [-h host] dbname\n", *argv);
  74.         exit (1);
  75.     }
  76.  
  77.     dbs = build_dblist();
  78.     nusers = count_users();
  79.     ndbs = count_dbs(dbs);
  80.  
  81.     printf("%d registered postgres users, %d database%s\n",
  82.        nusers, ndbs, (ndbs == 1 ? "" : "s"));
  83.     printf(" database name     DBA            classes  special  indices  archived  shared\n");
  84.  
  85.     while (dbs != (DBLIST) NULL) {
  86.  
  87.     show_stats(dbs);
  88.  
  89.     pfree(dbs->dbname);
  90.     pfree(dbs->dbowner);
  91.     old_dbs = dbs;
  92.     dbs = dbs->next;
  93.     pfree(old_dbs);
  94.     }
  95. }
  96.  
  97. /*
  98.  *  count_users() -- print stats on users.
  99.  *
  100.  *    This routine actually just counts the number of users registered
  101.  *    to postgres.
  102.  */
  103.  
  104. int
  105. count_users()
  106. {
  107.     PortalBuffer *portalbuf;
  108.     char *res;
  109.     int ngroups, ntups, grpno;
  110.     int nusers;
  111.  
  112.     /* open a connection to the backend */
  113.     PQsetdb("template1");
  114.  
  115.     /* we know the schema of the system catalogs... */
  116.     sprintf(Buf, "retrieve (pg_user.usename)");
  117.     res = PQexec(&Buf[0]);     
  118.  
  119.     if (*res == 'E') {
  120.         fprintf(stderr, "%s\npgstats failed", ++res);
  121.         exit(1);
  122.     }
  123.  
  124.     if (*res != 'P') {
  125.     fprintf(stderr, "pgstats:  no portal?!?\n");
  126.     exit (1);
  127.     }
  128.  
  129.     /* count result tuples -- get portal first */
  130.     portalbuf = PQparray(++res);
  131.     ngroups = PQngroups(portalbuf);
  132.  
  133.     /*
  134.      *  If we'd executed multiple queries, or if the target lists of the
  135.      *  returned tuples changed in mid-stream, there would be more than one
  136.      *  group of tuples in this portal.  As it is, that won't happen, but
  137.      *  we go ahead and code this correctly anyway.
  138.      */
  139.  
  140.     nusers = 0;
  141.     for (grpno = 0; grpno < ngroups; grpno++) {
  142.     nusers += PQntuplesGroup(portalbuf, grpno);
  143.     }
  144.  
  145.     /* shut down communications */
  146.     PQfinish();
  147.  
  148.     return (nusers);
  149. }
  150. /*
  151.  *  build_dblist() -- build a list of all databases that exist.
  152.  *
  153.  *    We know that the template database always exists.  We run a query
  154.  *    that returns the names of all databases by using the template db
  155.  *    to get an initial connection to postgres.  We fetch tuples one
  156.  *    at a time, and exploit our knowledge of the system catalog schema
  157.  *    to burst out the results into our list of databases.
  158.  */
  159.  
  160. DBLIST
  161. build_dblist()
  162. {
  163.     DBLIST dbhead, dblist, ndb;
  164.     PortalBuffer *portalbuf;
  165.     char *res;
  166.     int ngroups, ntups, nflds;
  167.     int grpno, tupno;
  168.  
  169.     dbhead = dblist = (DBLIST) NULL;
  170.  
  171.     /* open a connection to the backend */
  172.     PQsetdb("template1");
  173.  
  174.     /* we know the schema of the system catalogs... */
  175.     sprintf(Buf, "retrieve (p.datname, u.usename, u.oid)\
  176.           from p in pg_database, u in pg_user \
  177.           where p.datdba = u.oid");
  178.     res = PQexec(&Buf[0]);     
  179.  
  180.     if (*res == 'E') {
  181.         fprintf(stderr, "%s\npgstats failed", ++res);
  182.         exit(1);
  183.     }
  184.  
  185.     if (*res != 'P') {
  186.     fprintf(stderr, "pgstats:  no portal?!?\n");
  187.     exit (1);
  188.     }
  189.  
  190.     /*
  191.      *  Now get tuples from the result stream and add them to the dblist.
  192.      *  Need a portal for query results.  The backend returns the portal name
  193.      *  associated with our results in the stream, immediately after the 'P'.
  194.      */
  195.  
  196.     portalbuf = PQparray(++res);
  197.     ngroups = PQngroups(portalbuf);
  198.  
  199.     /*
  200.      *  If we'd executed multiple queries, or if the target lists of the
  201.      *  returned tuples changed in mid-stream, there would be more than one
  202.      *  group of tuples in this portal.  As it is, that won't happen, but
  203.      *  we go ahead and code this correctly anyway.
  204.      */
  205.  
  206.     for (grpno = 0; grpno < ngroups; grpno++) {
  207.     ntups = PQntuplesGroup(portalbuf, grpno);
  208.     if ((nflds = PQnfieldsGroup(portalbuf, grpno)) != 3) {
  209.         fprintf(stderr, "expected 3 attributes, got %d\n", nflds);
  210.         exit (1);
  211.     }
  212.  
  213.     /*
  214.      *  Copy values from the return stream into our db list.  We exploit
  215.      *  our knowledge of the target list here -- (datname, usename, oid)
  216.      *  -- from the query above.
  217.      */
  218.  
  219.     for (tupno = 0; tupno < ntups; tupno++) {
  220.         ndb = (DBLIST) palloc(sizeof(*ndb));
  221.  
  222.         ndb->dbname = get_attr(portalbuf, tupno, 0);
  223.         ndb->dbowner = get_attr(portalbuf, tupno, 1);
  224.         ndb->dbownerId = (ObjectId) atoi(PQgetvalue(portalbuf, tupno, 2));
  225.  
  226.         ndb->next = (DBLIST) NULL;
  227.  
  228.         if (dbhead == (DBLIST) NULL)
  229.         dbhead = dblist = ndb;
  230.         else {
  231.         dblist->next = ndb;
  232.         dblist = ndb;
  233.         }
  234.     }
  235.     }
  236.  
  237.     /* shut down communications */
  238.     PQfinish();
  239.  
  240.     return (dbhead);
  241. }
  242.  
  243. show_stats(db)
  244.     DBLIST db;
  245. {
  246.     PortalBuffer *portalbuf;
  247.     char *res;
  248.     int ngroups, ntups, nflds;
  249.     int grpno, tupno;
  250.     char *relisshared, *relkind, *relarch;
  251.     int nspecial, nindex, nclasses, narch, nshared;
  252.     bool istemplate;
  253.  
  254.     PQsetdb(db->dbname);
  255.  
  256.     sprintf(Buf, "retrieve (r.relisshared, r.relkind, r.relarch) \
  257.           from r in pg_class");
  258.  
  259.     res = PQexec(&Buf[0]);
  260.  
  261.     if (*res == 'E') {
  262.         fprintf(stderr, "%s\npgstats failed", ++res);
  263.         exit(1);
  264.     }
  265.  
  266.     if (*res != 'P') {
  267.     fprintf(stderr, "pgstats:  no portal?!?\n");
  268.     exit (1);
  269.     }
  270.  
  271.     portalbuf = PQparray(++res);
  272.     ngroups = PQngroups(portalbuf);
  273.  
  274.     nspecial = nindex = nclasses = narch = nshared = 0;
  275.  
  276.     for (grpno = 0; grpno < ngroups; grpno++) {
  277.     ntups = PQntuplesGroup(portalbuf, grpno);
  278.     nclasses += ntups;
  279.  
  280.     if ((nflds = PQnfieldsGroup(portalbuf, grpno)) != 3) {
  281.         fprintf(stderr, "expected 3 attributes, got %d\n", nflds);
  282.         exit (1);
  283.     }
  284.  
  285.     /* once again, we know what our target list looks like... */
  286.     for (tupno = 0; tupno < ntups; tupno++) {
  287.  
  288.         relisshared = get_attr(portalbuf, tupno, 0);
  289.         relkind = get_attr(portalbuf, tupno, 1);
  290.         relarch = get_attr(portalbuf, tupno, 2);
  291.  
  292.         switch (*relkind) {
  293.           case 'i':
  294.         nindex++;
  295.         break;
  296.  
  297.           case 's':
  298.         nspecial++;
  299.         break;
  300.  
  301.           default:
  302.         break;
  303.         }
  304.  
  305.         if (*relarch == 't')
  306.         narch++;
  307.  
  308.         if (*relisshared == 't')
  309.         nshared++;
  310.  
  311.         pfree(relisshared);
  312.         pfree(relkind);
  313.         pfree(relarch);
  314.     }
  315.     }
  316.  
  317.     printf("%s%*s  %s%*s  %4d    %4d     %4d      %4d     %4d\n",
  318.         db->dbname, 16 - strlen(db->dbname), "",
  319.         db->dbowner, 16 - strlen(db->dbowner), "",
  320.         nclasses, nspecial, nindex, narch, nshared);
  321.  
  322.     /* shut down communications */
  323.     PQfinish();
  324. }
  325.  
  326. char *
  327. get_attr(portalbuf, tupno, attno)
  328.     PortalBuffer *portalbuf;
  329.     int tupno;
  330.     int attno;
  331. {
  332.     char *attval;
  333.     char *result;
  334.  
  335.     attval = PQgetvalue(portalbuf, tupno, attno);
  336.     result = (char *) palloc(strlen(attval) + 1);
  337.     strcpy(result, attval);
  338.  
  339.     return (result);
  340. }
  341.  
  342. int
  343. count_dbs(dbs)
  344.     DBLIST dbs;
  345. {
  346.     int ndbs = 0;
  347.  
  348.     while (dbs != (DBLIST) NULL) {
  349.     ndbs++;
  350.     dbs = dbs->next;
  351.     }
  352.  
  353.     return (ndbs);
  354. }
  355.